package com.learnyou.server.xingzuo.biz.helper;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.learnyou.server.xingzuo.dto.pet.CosContentDTO;
import com.qcloud.cos.COSClient;
import com.qcloud.cos.ClientConfig;
import com.qcloud.cos.auth.BasicCOSCredentials;
import com.qcloud.cos.auth.COSCredentials;
import com.qcloud.cos.http.HttpProtocol;
import com.qcloud.cos.model.*;
import com.qcloud.cos.region.Region;
import com.squareup.okhttp.Connection;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

@Slf4j
public class CosHelper {
    private COSClient cosClient = null;

    private String bucketName = "";
    /**
     * constructor
     * @param secretId
     * @param secretKey
     * @param region
     */
    public CosHelper(String secretId, String secretKey, String region) {

        COSCredentials cred = new BasicCOSCredentials(secretId, secretKey);

        ClientConfig clientConfig = new ClientConfig(new Region(region));
        clientConfig.setHttpProtocol(HttpProtocol.https);
        // 3 生成 cos 客户端。
        this.cosClient = new COSClient(cred, clientConfig);
    }

    public CosHelper bucket(String bucketName) {
        this.bucketName = bucketName;
        return this;
    }


    /**
     * 移动桶对象到另一个桶的相同位置
     * @param sourceKey
     * @param targetBucketName
     */
    public void move(String sourceKey, String targetBucketName){
        this.cosClient.copyObject(bucketName, sourceKey, targetBucketName, sourceKey);
        this.cosClient.deleteObject(bucketName, sourceKey);
    }


    public void moveAll(String targetBucketName){
        ListObjectsRequest listObjectsRequest = new ListObjectsRequest(bucketName, (String) null, (String) null, (String) null, 1000);
        ObjectListing listing = this.cosClient.listObjects(listObjectsRequest);
        List<COSObjectSummary> objectSummaries = listing.getObjectSummaries();
        for (COSObjectSummary summary:
             objectSummaries) {
            move(summary.getKey(), targetBucketName);
        }
    }

    /**
     * 列出存储桶对象清单，最大10个
     * @return
     */
    public List<CosContentDTO> getPetObjects(){
        ListObjectsRequest listObjectsRequest = new ListObjectsRequest(bucketName, (String) null, (String) null, (String) null, 1000);
        ObjectListing listing = this.cosClient.listObjects(listObjectsRequest);

        return listing.getObjectSummaries().stream().map(COSObjectSummary::getKey)
                .filter(this::filterKey)
                .map(this::selectObjectContent).collect(Collectors.toList());
    }

    /**
     * 按key清单读取存储对象内容
     * @param keys
     * @return
     */
    public List<CosContentDTO> getPetObjects(List<String> keys){
        return keys.stream()
                .filter(this::filterKey)
                .map(this::selectObjectContent).collect(Collectors.toList());
    }


    /**
     * 过滤掉不需要处理的key
     * @param key
     * @return
     */
    private boolean filterKey(String key) {
        return !StrUtil.contains(key, "cos-access-log");
    }

    /**
     * 读取存储对象内容列表，按行读取
     * @param key
     * @return
     */
    public CosContentDTO selectObjectContent(String key){
        COSObjectInputStream inputStream = readObject(key);
        List<String> lines = new ArrayList<String>();
        lines = IoUtil.readUtf8Lines(inputStream, lines);
        return new CosContentDTO(key, lines);
    }

    /**
     * 支持本地图片和网路图片
     * @param saveTo
     * @param file
     * @return
     */
    public String saveObject(String saveTo, String file) {
        if (isUrl(file)) {
            try {
                URL url = new URL(file);
                URLConnection urlConnection = url.openConnection();
                InputStream is = urlConnection.getInputStream();
                if (Objects.nonNull(is)) {
                    int size = urlConnection.getContentLength();
                    int availableSize = is.available();
                    String type = urlConnection.getContentType();
                    log.info("size: {}, availableSize: {}, Type: {}", size, availableSize, type);
                    return saveObject(saveTo, is, size);
                } else {
                    return null;
                }
            } catch (IOException ex) {
                log.error("err:", ex);
                return null;
            }
        } else {
            PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, saveTo, new File(file));
            cosClient.putObject(putObjectRequest);
            return saveTo;
        }
    }

    /**
     * 判断URL是否合法
     * @param content
     * @return
     */
    public static boolean isUrl(String content) {
        String regx = "^(http[s]?://\\S+\\.\\S+)";
        return Pattern.matches(regx, content);
    }

    public String saveObject(String saveTo, InputStream inputStream, long size) {
        ObjectMetadata objectMetadata = new ObjectMetadata();
        objectMetadata.setContentLength(size);
        PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, saveTo, inputStream, objectMetadata);
        cosClient.putObject(putObjectRequest);
        return saveTo;
    }

    public String saveObject(MediaSaveObject mediaSaveObject) {
        return saveObject(mediaSaveObject.getSaveTo(), mediaSaveObject.getInputStream(), mediaSaveObject.getSize());
    }

    public List<String> saveObject(List<MediaSaveObject> mediaSaveObject) {
        List<String> result = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(mediaSaveObject)) {
            mediaSaveObject.forEach(item -> {
                result.add(saveObject(item));
            });
        }
        return result;
    }

    public COSObjectInputStream readObject(String target) {
        return cosClient.getObject(bucketName, target).getObjectContent();
    }

    public void removeObject(String target) {
        cosClient.deleteObject(bucketName, target);
    }

    public static MediaSaveObject buildMediaSaveObject(String mediaSource, MultipartFile mediaFile) throws IOException {
        String fileName = mediaFile.getOriginalFilename();

        String fileSuffix = FileUtil.extName(fileName);
        String targetFileName = mediaSource + "_" + IdUtil.getSnowflake().nextIdStr() +"."+ fileSuffix;

        return new MediaSaveObject(targetFileName, mediaFile.getInputStream(), mediaFile.getSize());

    }

    public static List<MediaSaveObject> buildMediaSaveObjectList(String mediaSource, List<MultipartFile> mediaFile) throws IOException {
        List<MediaSaveObject> files = new ArrayList<>();
        for (MultipartFile file :
                mediaFile) {
            files.add(buildMediaSaveObject(mediaSource, file));
        }
        return files;
    }
}
